package com.sc.server.system.batch.conf;


import com.sc.server.system.auth.entity.Menu;
import com.sc.server.system.auth.service.IMenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.*;
import org.springframework.batch.item.database.JpaPagingItemReader;
import org.springframework.batch.item.database.orm.JpaNativeQueryProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by EalenXie on 2018/9/10 14:50.
 * :@EnableBatchProcessing提供用于构建批处理作业的基本配置
 */
@Configuration
@EnableBatchProcessing
public class DataBatchConfiguration {
    private static final Logger log = LoggerFactory.getLogger(DataBatchConfiguration.class);

    @Resource
    private JobBuilderFactory jobBuilderFactory;    //用于构建JOB
    @Resource
    private StepBuilderFactory stepBuilderFactory;  //用于构建Step
    @Resource
    private JobListener jobListener;            //简单的JOB listener
    @Autowired
    private IMenuService menuService;
    /**
     * 一个简单基础的Job通常由一个或者多个Step组成
     */
    @Bean
    public Job dataHandleJob() {
        return jobBuilderFactory.get("dataHandleJob").
                incrementer(new RunIdIncrementer()).
                //start是JOB执行的第一个step
                start(handleDataStep()).
//                next(xxxStep()).
//                next(xxxStep()).
                //设置了一个简单JobListener               ...
             listener(jobListener).
                build();
    }

    /**
     * 一个简单基础的Step主要分为三个部分
     * ItemReader : 用于读取数据
     * ItemProcessor : 用于处理数据
     * ItemWriter : 用于写数据
     */
    @Bean
    public Step handleDataStep() {
        // <输入,输出> 。chunk通俗的讲类似于SQL的commit; 这里表示处理(processor)100条后写入(writer)一次。
        return stepBuilderFactory.get("getData").<Menu, Menu>chunk(100).
                //捕捉到异常就重试,重试100次还是异常,JOB就停止并标志失败
                faultTolerant().retryLimit(3).retry(Exception.class).skipLimit(100).skip(Exception.class).
                //指定ItemReader
                reader(getDataReader()).
                //指定ItemProcessor
                processor(getDataProcessor()).
                //指定ItemWriter
                writer(getDataWriter()).
                build();
    }

    @Bean
    public ItemReader<? extends Menu> getDataReader() {
        Menu menu=menuService.selectById("5");
       return new ItemReader<Menu>() {
           @Override
           public Menu read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
               return  menu;
           }
       };
    }

    @Bean
    public ItemProcessor<Menu, Menu> getDataProcessor() {
        return new ItemProcessor<Menu, Menu>() {
            @Override
            public Menu process(Menu menu) throws Exception {
                log.info("processor data : " + menu.toString());  //模拟  假装处理数据,这里处理就是打印一下
                return menu;
            }
        };
//        lambda也可以写为:
//        return Menu -> {
//            log.info("processor data : " + Menu.toString());
//            return Menu;
//        };
    }

    @Bean
    public ItemWriter<Menu> getDataWriter() {
        return list -> {
            for (Menu menu : list) {
                log.info("write data : " + menu); //模拟 假装写数据 ,这里写真正写入数据的逻辑
            }
        };
    }
}
